import { CollectionProp } from '../../common/property/collection-property-config';
import { BeforeOpenModalResult, ElementPropertyConfig } from '@farris/ide-property-panel';
import { DgControl } from '../../../../utils/dg-control';
import { FormPropertyChangeObject } from '../../../../entity/property-change-entity';
import { CodeEditorComponent } from '@farris/designer-devkit';
import { FormSchemaEntity, FormSchemaEntityField } from '@farris/designer-services';
import { GroupFieldEditorComponent } from '../../common/property/editor/group-field-editor/group-field-editor.component';
import { GroupFieldConverter } from '../../common/property/editor/group-field-editor/group-field-converter';
import { EventsEditorFuncUtils } from '../../../../utils/events-editor-func';
import { ControlAppearancePropertyConfig } from '../../../../utils/appearance-property-config';
import { TemplateBindingEditorComponent } from '../../list-view/property/editor/template-binding-editor/template-binding-editor.component';
import { CalendarFieldsEditorComponent } from './editor/calendar-fields-editor/calendar-fields-editor.component';
import { CalendarFieldsConverter } from './editor/calendar-fields-editor/calendar-fields-converter';
import { PlaceDataSourceConverter } from './editor/place-datasource-selector/place-datasource-converter';
import { PlaceDataSourceSelectorComponent } from './editor/place-datasource-selector/place-datasource-selector.component';
import { PlaceTemplateEditorComponent } from './editor/place-template-editor/place-template-editor.component';
import { PlaceFieldSelectorComponent } from './editor/place-field-selector/place-field-selector.component';
import { ResolveTemplateFieldUtil } from './editor/resolve-template-fields';

export class AppointmentCalendarProp extends CollectionProp {

    propertyConfig: ElementPropertyConfig[];


    getPropConfig(propertyData: any): ElementPropertyConfig[] {
        this.propertyConfig = [];
        const viewModelId = this.viewModelId;

        // 基本信息属性
        const basicPropConfig = this.getBasicPropConfig(propertyData, viewModelId);
        this.propertyConfig.push(basicPropConfig);

        // 样式属性
        const appearanceStylePropConfig = ControlAppearancePropertyConfig.getAppearanceStylePropConfigs(propertyData);
        this.propertyConfig = this.propertyConfig.concat(appearanceStylePropConfig);


        // 外观属性
        const appearancePropConfig = this.getAppearanceProperties(propertyData);
        this.propertyConfig.push(appearancePropConfig);

        // 行为属性
        const behaviorPropConfig = this.getBehaviorProperties(propertyData, viewModelId);
        this.propertyConfig.push(behaviorPropConfig);

        // 地点属性
        const placePropConfig = this.getPlacePropConfig(propertyData, viewModelId);
        this.propertyConfig.push(placePropConfig);

        // 日视图属性
        const dayViewPropConfig = this.getDayViewPropConfig(propertyData, viewModelId);
        this.propertyConfig.push(dayViewPropConfig);

        // 预定配置属性
        const appointmentPropConfig = this.getAppointmentPropConfig(propertyData, viewModelId);
        this.propertyConfig.push(appointmentPropConfig);

        // 预定配置属性
        const detailPanelPropConfig = this.detailPanelPropConfig(propertyData, viewModelId);
        this.propertyConfig.push(detailPanelPropConfig);

        // 事件属性
        const eventPropConfig = this.getEventPropConfig(propertyData, viewModelId);
        this.propertyConfig.push(eventPropConfig);

        return this.propertyConfig;
    }
    private getBasicPropConfig(propertyData: any, viewModelId: string): ElementPropertyConfig {

        return {
            categoryId: 'basic',
            categoryName: '基本信息',
            properties: [
                {
                    propertyID: 'id',
                    propertyName: '标识',
                    propertyType: 'string',
                    description: '组件的id',
                    readonly: true
                },
                {
                    propertyID: 'type',
                    propertyName: '控件类型',
                    propertyType: 'select',
                    description: '组件的类型',
                    iterator: [{ key: propertyData.type, value: DgControl.AppointmentCalendar.name }],
                }
            ],
        };
    }

    getAppearanceProperties(propertyData: any): ElementPropertyConfig {
        const self = this;
        return {
            categoryId: 'appearance',
            categoryName: '外观',
            properties: [
                {
                    propertyID: 'viewType',
                    propertyName: '默认视图类型',
                    propertyType: 'select',
                    description: '组件默认显示的视图类型',
                    iterator: [{ key: 'day', value: '日视图' }, { key: 'week', value: '周视图' }]
                },
                {
                    propertyID: 'placeNameWidth',
                    propertyName: '地点列宽度',
                    propertyType: 'number',
                    decimals: 0,
                    min: 150
                },
                {
                    propertyID: 'rowHeight',
                    propertyName: '日视图行高',
                    propertyType: 'number',
                    decimals: 0,
                    min: 62
                },
                {
                    propertyID: 'weekRowHeight',
                    propertyName: '周视图行高',
                    propertyType: 'number',
                    decimals: 0,
                    min: 85
                },
                {
                    propertyID: 'weekCellWidth',
                    propertyName: '周视图列宽度',
                    propertyType: 'number',
                    decimals: 0,
                    min: 150
                },
            ]
        };
    }

    getBehaviorProperties(propertyData: any, viewModelId: string) {
        const visibleProp = this.getVisiblePropertyEntity(propertyData, viewModelId);

        return {
            categoryId: 'behavior',
            categoryName: '行为',
            properties: [
                visibleProp
            ]
        };
    }
    getDayViewPropConfig(propertyData: any, viewModelId: string): ElementPropertyConfig {
        const self = this;
        return {
            categoryId: 'dayView',
            categoryName: '日视图配置',
            properties: [
                {
                    propertyID: 'contentTemplate',
                    propertyName: '日视图预定信息模板',
                    propertyType: 'modal',
                    editor: TemplateBindingEditorComponent,
                    editorParams: {
                        listViewId: propertyData.id,
                        templateUri: 'assets/form/preset-template/appointment-calendar-template.json',
                        schemaFields: [],
                        viewModelId: this.viewModelId
                    },
                    beforeOpenModal(): BeforeOpenModalResult {
                        // 取字段最新值
                        this.editorParams.schemaFields = self.getPanelMappingFields();
                        return { result: true, message: '' };
                    }
                },
                {
                    propertyID: 'dayViewCls',
                    propertyName: '日视图自定义样式',
                    propertyType: 'modal',
                    editor: CodeEditorComponent,
                    editorParams: {
                        language: 'javascript',
                        exampleCode: '(item) => {\r\n    const data = item.data;\r\n    return {\r\n        gray: data.level === \'1\',\r\n        blue: data.level === \'2\',\r\n        ' +
                            'pink: data.level === \'3\',\r\n        red: data.level === \'4\'\r\n    };\r\n}\r\n\r\n注：根据预定类型返回不同的样式，其中level为预定类型字段在数据库中的字段编号。'
                    }
                },
                {
                    propertyID: 'reservationTitle',
                    propertyName: '新增预定文本',
                    propertyType: 'string',
                    description: '鼠标滑过日视图空白单元格时显示的文本'
                }
            ]
        };
    }
    getPlacePropConfig(propertyData: any, viewModelId: string): ElementPropertyConfig {
        const self = this;
        const viewModel = self.domService.getViewModelById(viewModelId);

        return {
            categoryId: 'place',
            categoryName: '地点配置',
            properties: [
                {
                    propertyID: 'placeTitle',
                    propertyName: '地点列标题',
                    propertyType: 'string',
                    description: '地点的展示文本'
                },
                {
                    propertyID: 'placeDataSource',
                    propertyName: '地点数据源',
                    propertyType: 'modal',
                    description: '选择地点数据源视图对象',
                    editor: PlaceDataSourceSelectorComponent,
                    editorParams: propertyData,
                    converter: new PlaceDataSourceConverter()
                },
                {
                    propertyID: 'placeDataSourceUrl',
                    propertyName: '地点数据源请求url',
                    propertyType: 'string',
                    description: '获取地点列表的API地址',
                    readonly: true,
                    visible: propertyData.placeDataSource
                },
                {
                    propertyID: 'placeDataSourceUrlType',
                    propertyName: '地点数据源请求类型',
                    propertyType: 'select',
                    description: '地点数据源请求类型',
                    iterator: [{ key: 'PUT', value: 'PUT' }, { key: 'POST', value: 'POST' }, { key: 'GET', value: 'GET' }],
                    readonly: true,
                    visible: propertyData.placeDataSource
                },
                {
                    propertyID: 'placeNameTemplate',
                    propertyName: '地点展示模板',
                    propertyType: 'modal',
                    editor: PlaceTemplateEditorComponent,
                    editorParams: propertyData,
                    beforeOpenModal(): BeforeOpenModalResult {
                        if (!propertyData.placeDataSource) {
                            return { result: false, message: '请先选择地点数据源' };
                        }
                        this.editorParams = propertyData;
                        return { result: true, message: '' };
                    },
                    visible: propertyData.placeDataSource

                },
                {
                    propertyID: 'placeIdField',
                    propertyName: '地点标识字段',
                    propertyType: 'modal',
                    editor: PlaceFieldSelectorComponent,
                    editorParams: {
                        voId: propertyData.placeDataSource && propertyData.placeDataSource.voId
                    },
                    beforeOpenModal(): BeforeOpenModalResult {
                        if (!propertyData.placeDataSource) {
                            return { result: false, message: '请先选择地点数据源' };
                        }
                        this.editorParams.voId = propertyData.placeDataSource && propertyData.placeDataSource.voId;
                        return { result: true, message: '' };
                    },
                    visible: propertyData.placeDataSource
                },
                {
                    propertyID: 'placeNameField',
                    propertyName: '地点名称字段',
                    propertyType: 'modal',
                    editor: PlaceFieldSelectorComponent,
                    editorParams: {
                        voId: propertyData.placeDataSource && propertyData.placeDataSource.voId
                    },
                    beforeOpenModal(): BeforeOpenModalResult {
                        if (!propertyData.placeDataSource) {
                            return { result: false, message: '请先选择地点数据源' };
                        }
                        this.editorParams.voId = propertyData.placeDataSource && propertyData.placeDataSource.voId;
                        return { result: true, message: '' };
                    },
                    visible: propertyData.placeDataSource
                }
            ],
            setPropertyRelates(changeObject, data, parameters?) {
                switch (changeObject.propertyID) {
                    case 'placeDataSource': {
                        this.properties.forEach(prop => {
                            if (prop.propertyID !== 'placeTitle' && prop.propertyID !== 'placeDataSource') {
                                prop.visible = changeObject.propertyValue ? true : false;
                            }
                        });
                        break;
                    }

                    case 'placeIdField': case 'placeNameField': {
                        // 修改地点标识、名称列后需要同步命令中的地点参数
                        const placeIdParam = propertyData.placeIdField;
                        const placeNameParam = propertyData.placeNameField;
                        const addNode = viewModel.commands.find(item => item.handlerName === 'OpenAppAndAdd' && (item.cmpId === '70b4abd4-9f2c-4b7c-90e9-6ac6f4b74c72'));
                        if (addNode && addNode.params) {
                            addNode.params.find(item => item.name === 'params').value =
                                "{\"action\":\"LoadAndAdd1\",\"start\":\"{EVENTPARAM~/start}\",\"end\":\"{EVENTPARAM~/end}\",\"placeId\":\"{EVENTPARAM~/place/" + placeIdParam + "}\",\"placeName\":\"{EVENTPARAM~/place/" + placeNameParam + "}\"}";
                        }
                        break;
                    }
                }
            },
        };
    }

    getAppointmentPropConfig(propertyData: any, viewModelId: string): ElementPropertyConfig {

        return {
            categoryId: 'appointment',
            categoryName: '预定配置',
            enableCascade: true,
            parentPropertyID: 'reserveInfoFields',
            propertyData: propertyData.reserveInfoFields,
            properties: [
                {
                    propertyID: 'idField',
                    propertyName: '标识字段',
                    propertyType: 'modal',
                    editor: GroupFieldEditorComponent,
                    editorParams: {
                        viewModelId,
                        selectNumber: 1,
                        resultType: 'string'
                    },
                    converter: new GroupFieldConverter()
                },
                {
                    propertyID: 'placeid',
                    propertyName: '地点标识字段',
                    propertyType: 'modal',
                    editor: GroupFieldEditorComponent,
                    editorParams: {
                        viewModelId,
                        selectNumber: 1,
                        resultType: 'string'
                    },
                    converter: new GroupFieldConverter()
                },
                {
                    propertyID: 'title',
                    propertyName: '预定主题名称字段',
                    propertyType: 'modal',
                    editor: GroupFieldEditorComponent,
                    editorParams: {
                        viewModelId,
                        selectNumber: 1,
                        resultType: 'string'
                    },
                    converter: new GroupFieldConverter()
                },
                {
                    propertyID: 'startDate',
                    propertyName: '开始时间字段',
                    propertyType: 'modal',
                    editor: GroupFieldEditorComponent,
                    editorParams: {
                        viewModelId,
                        selectNumber: 1,
                        resultType: 'string'
                    },
                    converter: new GroupFieldConverter()
                },
                {
                    propertyID: 'endDate',
                    propertyName: '结束时间字段',
                    propertyType: 'modal',
                    editor: GroupFieldEditorComponent,
                    editorParams: {
                        viewModelId,
                        selectNumber: 1,
                        resultType: 'string'
                    },
                    converter: new GroupFieldConverter()
                }
            ]
        };
    }

    detailPanelPropConfig(propertyData: any, viewModelId: string): ElementPropertyConfig {
        const self = this;
        return {
            categoryId: 'detailPanel',
            categoryName: '详情卡片配置',
            properties: [
                {
                    propertyID: 'detailColumns',
                    propertyName: '展示列',
                    propertyType: 'modal',
                    editor: CalendarFieldsEditorComponent,
                    editorParams: {
                        viewModelId
                    },
                    converter: new CalendarFieldsConverter()
                },
                {
                    propertyID: 'detailBadgeTemplate',
                    propertyName: '详情徽章模板',
                    propertyType: 'modal',
                    editor: TemplateBindingEditorComponent,
                    editorParams: {
                        listViewId: propertyData.id,
                        templateUri: 'assets/form/preset-template/appointment-calendar-template.json',
                        schemaFields: [],
                        viewModelId: this.viewModelId
                    },
                    beforeOpenModal(): BeforeOpenModalResult {
                        // 取字段最新值
                        this.editorParams.schemaFields = self.getPanelMappingFields();
                        return { result: true, message: '' };
                    }
                },
                {
                    propertyID: 'detailCls',
                    propertyName: '详情卡片自定义样式',
                    propertyType: 'modal',
                    editor: CodeEditorComponent,
                    editorParams: {
                        language: 'javascript',
                        exampleCode: '(item) => {\r\n    const data = item.data;\r\n    return {\r\n        gray: data.level === \'1\',\r\n        blue: data.level === \'2\',\r\n        ' +
                            'pink: data.level === \'3\',\r\n        red: data.level === \'4\'\r\n    };\r\n}\r\n\r\n\r\n注：根据预定类型返回不同的样式，其中level为预定类型字段在数据库中的字段编号。'
                    }
                }
            ]
        };
    }

    getEventPropConfig(propertyData: any, viewModelId: string): ElementPropertyConfig {
        const self = this;
        const domService = this.domService;
        const webCmdService = this.webCmdService;
        const formBasicService = this.formBasicService;
        const eventEditorService = this.eventEditorService;
        const eventList = [
            {
                label: 'filterChange',
                name: '日期变化后事件'
            },
            {
                label: 'selectChange',
                name: '选中事件'
            },
            {
                label: 'editHandler',
                name: '详情卡片编辑事件'
            },
            {
                label: 'removeHandler',
                name: '详情卡片删除事件'
            },
            {
                label: 'reservation',
                name: '日视图新增预定事件'
            }
        ];
        return {
            categoryId: 'eventsEditor',
            categoryName: '事件',
            hideTitle: true,
            properties: EventsEditorFuncUtils.formProperties(eventEditorService, formBasicService, domService, webCmdService, propertyData, viewModelId, eventList),
            tabId: 'commands',
            tabName: '交互',
            setPropertyRelates(changeObject: FormPropertyChangeObject, data, parameters) {
                delete propertyData[viewModelId];
                EventsEditorFuncUtils.saveRelatedParameters(eventEditorService, domService, webCmdService, propertyData, viewModelId, eventList, parameters);
                this.properties = EventsEditorFuncUtils.formProperties(eventEditorService, formBasicService, domService, webCmdService, propertyData, viewModelId, eventList);

            }
        };
    }

    private getPanelMappingFields(): FormSchemaEntityField[] {
        if (this.viewModelId) {
            const viewModel = this.domService.getViewModelById(this.viewModelId);
            if (!viewModel) {
                return [];
            }
            const entities = this.schemaService.getSchemaEntities();
            if (!entities || !entities.length) {
                return [];
            }
            const fieldServ = new ResolveTemplateFieldUtil();
            const allFieldsInSpecialEntity = fieldServ.getSimpleTableFieldsByBindTo(entities, viewModel.bindTo);
            return allFieldsInSpecialEntity;
        }
        return [];
    }

}
